﻿namespace ThreeDI.UI.Abstraction
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Windows.Forms;
    using System;
    using System.Collections.Generic;
    using System.Text;
    using SlimDX;
    using SlimDX.Direct3D9;
    using SlimDX.Windows;
    
    using Device = SlimDX.Direct3D9.Device;

    using Format = SlimDX.Direct3D9.Format;

    using PresentFlags = SlimDX.Direct3D9.PresentFlags;

    using SwapChain = SlimDX.Direct3D9.SwapChain;

    using SwapEffect = SlimDX.Direct3D9.SwapEffect;

    public abstract class Application : RenderForm
    {
        #region Fields

        
        private Device _Device;
        private List<TransformObject> MeshList;
        #endregion Fields

        #region Constructors

        public Application()
        {
            Initilize();
        }

        #endregion Constructors

        #region Properties

      
        public Device Device
        {
            get
            {
                return _Device;
            }
        }

        
        
        public List<TransformObject> meshList { get; set; }

        #endregion Properties

        #region Methods

        public void BeginScene(Color clearColor)
        {
            //_Device.Clear(ClearFlag.Target | ClearFlags.ZBuffer | ClearFlags.Stencil, clearColor, 1.0f, 0);
            _Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, clearColor, 1.0f, 0);
            _Device.BeginScene();
        }
        public void EndScene()
        {
            _Device.EndScene();
        }
        public void Present()
        {
            Device.Present();
        }

        public int Width { get ; set; }
        public int Height { get; set; }
        public SlimDX.Direct3D9.Format ScreenFormat { get; set; }

        public void Initilize()
        {
            Direct3D direct3d = new Direct3D();
            Width = direct3d.GetAdapterDisplayMode(0).Width;
            Height = direct3d.GetAdapterDisplayMode(0).Height;
            ScreenFormat = direct3d.GetAdapterDisplayMode(0).Format;


            PresentParameters present = new PresentParameters();
            present.BackBufferWidth = Width;
            present.BackBufferHeight =Height;
            present.BackBufferFormat =ScreenFormat;
            present.BackBufferCount = 1;
            present.SwapEffect = SwapEffect.Discard;
            present.DeviceWindowHandle = this.Handle;
            present.Windowed = true;
            present.EnableAutoDepthStencil = true;
            present.AutoDepthStencilFormat = Format.D16;
            present.PresentFlags = PresentFlags.DiscardDepthStencil;
            present.PresentationInterval = PresentInterval.Default;
            
            _Device = new Device(direct3d, 0, DeviceType.Hardware, this.Handle,
                                 SlimDX.Direct3D9.CreateFlags.SoftwareVertexProcessing, present);
            
        //    _camera = new FlexableCamera(this);

            _Device.SetRenderState(RenderState.ZEnable, true);
            // Turn on ambient lighting 
            _Device.SetRenderState(RenderState.Ambient, System.Drawing.Color.White.ToArgb());
            // Load the mesh from the specified file
            
            this.Load();
        }
        public void Run()
        {
            SlimDX.Windows.MessagePump.Run(this, this.Render);
        }
        public void CreateSpotLight(int ID, Vector3 position, Color color)
        {
            Light lightData = new Light();
            lightData.Type = LightType.Spot;
            lightData.Position = position;
            lightData.Diffuse = color;
            lightData.Ambient = Color.FromArgb((int) (color.ToArgb()*0.6f));
            lightData.Specular = Color.FromArgb((int)(color.ToArgb() * 0.6f));
            
            _Device.SetLight(ID, lightData);            
        }
        public void CreatePointLight(int ID, Vector3 position, Color color)
        {
            Light lightData = new Light();
            lightData.Type = LightType.Point;
            lightData.Position = position;
            lightData.Diffuse = color;
            lightData.Ambient = Color.FromArgb((int) (color.ToArgb()*0.6f));
            lightData.Specular = Color.FromArgb((int)(color.ToArgb() * 0.6f));
            _Device.SetLight(ID, lightData);
        }
        public void CreateDirectionalLight(int ID, Vector3 position, Vector3 direction, Color color)
        {
            Light lightData = new Light();
            lightData.Type = LightType.Directional;
            lightData.Position = position;
            lightData.Diffuse = color;
            lightData.Direction = direction;
            lightData.Ambient = Color.FromArgb((int)(color.ToArgb() * 0.6f));
            lightData.Specular = Color.FromArgb((int)(color.ToArgb() * 0.6f));
            _Device.SetLight(ID, lightData);
        }
        //must override
        public abstract void Render();
        public abstract void Load();
        public virtual void SetupLight()
        {
            RenderState State = new RenderState();
            _Device.SetRenderState(RenderState.Lighting, true);

        }
        #endregion Methods

        
        private void Application_Load(object sender, System.EventArgs e)
        {

        }

    }
}